<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="NormalVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform mat4 u_PvM4;
    void main(){
        gl_Position = u_PvM4 * a_Position;
        gl_PointSize = 20.0;
    }
</script>
<script id="NormalFS" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    void main(){
        gl_FragColor = u_Color;
    }
</script>
<script id="LightVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec3 a_Normal;
    uniform float u_PointSize;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    varying vec3 v_Normal;
    varying vec3 v_Position;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        gl_PointSize = u_PointSize;
        v_Normal = a_Normal;
        v_Position = vec3(a_Position);
    }
</script>
<script id="LightFS" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec3 u_Kd;//漫反射系数
    uniform vec3 u_Ks;//高光反射系数
    uniform vec3 u_Ka;//环境反射系数
    uniform vec3 u_Eye;//视点
    uniform vec3 u_LightDir;//平行光
    uniform vec3 u_Color;//物体颜色
    varying vec3 v_Normal;//法线
    varying vec3 v_Position;
    void main(){

        vec3 eyeDir = normalize(u_Eye - v_Position);
        vec3 el = eyeDir + u_LightDir;
        vec3 h = el / length(el);

        //漫反射
        vec3 Ld = u_Kd * u_Color * max(0.0, dot(v_Normal, u_LightDir));
        //镜面反射
        vec3 Ls = u_Ks * pow(max(0.0, dot(v_Normal, h)), 64.0);
        //环境反射
        vec3 La = u_Ka * 0.5;

        //Blinn-Phong反射
        vec3 l = Ls + Ld + La;

        gl_FragColor = vec4(l, 1.0);
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, SphereGeometry, PerspectiveCamera, } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Sphere from '../js/Sphere.js'
    import Control from '../js/Control.js'
    import { getTrangleNormal, getTriangleVertices } from '../js/ShadingFrequency.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'

    // 0,1,2,
    // 0,2,3,
    // 0,3,1,
    // 1,4,5,
    // 1,5,2,
    // 2,5,6,
    // 2,6,3,
    // 3,6,4,
    // 3,4,1,
    // 4,5,7,
    // 5,6,7,
    // 6,4,7,

    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.enable(gl.DEPTH_TEST);
    // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion


    const scene = new Scene({ gl: gl });
    scene.regProgram('light', {
        program: CreateProgram(gl,
            document.querySelector('#LightVS').innerText,
            document.querySelector('#LightFS').innerText),
        attribs: ['a_Position', 'a_Normal'],
        uniforms: ['u_PvM4', 'u_ModelM4', 'u_PointSize', 'u_Color',
            'u_LightDir', 'u_Kd', 'u_Ks', 'u_Ka', 'u_Eye']
    });
    scene.regProgram('normal', {
        program: CreateProgram(gl,
            document.querySelector('#NormalVS').innerText,
            document.querySelector('#NormalFS').innerText),
        attribs: ['a_Position'],
        uniforms: ['u_PvM4', 'u_Color']
    });


    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4
    });

    const w = 10;
    const h = 10;
    const mySphere = new Sphere(0.5, w, h);
    //console.log((h - 2) * w * 2 + w * 2)

    console.log(mySphere)

    const sphereVertices = mySphere.vertices;
    const sphereElements = mySphere.elements;

    const vertices = getTriangleVertices(sphereVertices, sphereElements);
    const normals = getTrangleNormal(sphereVertices, sphereElements);


    const LightDir = new Vector3(0.5, 1, 1).normalize();//光线方向
    const Kd = [0.7, 0.7, 0.7];//漫反射系数
    const Ks = [0.1, 0.1, 1];//镜面反射系数
    const Ka = [0.2, 0.2, 0.2];//环境反射系数

    //Axis
    {
        scene.add(new Obj3D().createAxis(gl, 'normal'));
    }

    //球体
    {
        let obj01 = new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(vertices) },
                    'a_Normal': { size: 3, array: new Float32Array(normals) },
                },
            }),
            mat: new Mat({
                program: 'light',
                mode: ['TRIANGLES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
                    'u_Kd': { type: 'uniform3fv', value: Kd },
                    'u_Ks': { type: 'uniform3fv', value: Ks },
                    'u_Ka': { type: 'uniform3fv', value: Ka },
                    'u_LightDir': { type: 'uniform3fv', value: [...LightDir] },
                    'u_Eye': { type: 'uniform3fv', value: [...cameraController.eye] },
                    'u_Color': { type: 'uniform3fv', value: [1, 1, 1] },
                },
            }),
        });
        scene.add(obj01);
    }

    //法线
    {
        const normalArr = getNormalize(vertices, normals);
        let normalObj = new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(normalArr) },
                },
            }),
            mat: new Mat({
                program: 'normal',
                mode: ['LINES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_Color': { type: 'uniform4fv', value: [1, 1, 1, 1] },
                },
            }),
        });
        scene.add(normalObj);
    }

    draw();


    let set = 0;
    (function ani() {
        // set += 1;
        scene.setUniform('u_LightDir', { value: [...LightDir.clone().applyMatrix4(new Matrix4().makeRotationY(set % 360 * Math.PI / 180))] });

        draw();
        requestAnimationFrame(ani);
    })();

    function draw() {
        // scene.setUniform('u_Eye', { value: [...cameraController.eye] });
        scene.setUniform('u_PvM4', { value: pvM4.elements });
        scene.draw();
    }


    function getNormalize(nodeArr, normals, length = 0.2) {
        const normalArr = [];
        for (let i = 0; i < normals.length; i += 3) {
            const curNormal = new Vector3(normals[i], normals[i + 1], normals[i + 2]);
            const node1 = new Vector3(nodeArr[i], nodeArr[i + 1], nodeArr[i + 2]);

            normalArr.push(...node1)
            normalArr.push(...curNormal.clone().setLength(length).add(node1));
        }
        return normalArr;
    }

</script>

</html>